import { Enum, ImageAsset, Sprite, SpriteFrame, UITransform, Widget, assetManager, view } from 'cc';
import { ccclass, cccomponent, ccmodifier, property } from '../decorators';
import { BaseView } from './BaseView';
import { app } from '../application';

/** 适配模式 */
const FitMode = Enum({
    /** 保留原始状态 */
    None: 0,
    /** 作用拉伸 */
    FitWidth: 1,
    /** 上下拉伸 */
    FitHeight: 2,
    /** 拉伸以适应屏幕 */
    FitAll: 3,
    /** 等比缩放 */
    Auto: 4,
});

/**
 * - 作者: DoooReyn
 * - 日期: 2023.10.31
 * - 名称: Background
 * - 描述: 视图-背景层
 */
@ccclass()
@ccmodifier('Background')
export class Background extends BaseView {
    @property({ type: FitMode, displayName: '适配模式' })
    private editorFitMode = FitMode.None;

    /** 背景精灵 */
    @cccomponent(Sprite, 'Bkg')
    private __bkg: Sprite;

    /** 适配组件 */
    @cccomponent(Widget, 'Bkg')
    private __widget: Widget;

    /** UI 变换组件 */
    @cccomponent(UITransform, 'Bkg')
    private __tranform: UITransform;

    /** 原始背景 SpriteFrame */
    private __raw: SpriteFrame | null;

    /** 初始化 */
    public async init() {
        if (this.__bkg.spriteFrame) {
            this.__raw = this.__bkg.spriteFrame;
        }
        await super.init();
    }

    public async exit() {
        this.__bkg.spriteFrame = null;
        await super.exit();
    }

    public async enter(): Promise<void> {
        this.reset();
        await super.enter();
    }

    /** 恢复原始背景 */
    public reset() {
        if (this.__raw) {
            this.__bkg.spriteFrame = this.__raw;
        }
    }

    /** 当前适配模式 */
    public get fitMode() {
        return this.editorFitMode;
    }

    /**
     * 设置适配模式
     * @param mode 适配模式
     */
    public set fitMode(mode: (typeof FitMode)[keyof typeof FitMode]) {
        this.editorFitMode = mode;
        switch (mode) {
            case FitMode.None:
                this.__widget.enabled = false;
                if (this.__bkg.spriteFrame) {
                    this.__tranform.setContentSize(this.__bkg.spriteFrame.width, this.__bkg.spriteFrame.height);
                }
                break;
            case FitMode.FitWidth:
                this.__widget.left = 0;
                this.__widget.right = 0;
                this.__widget.isAlignLeft = true;
                this.__widget.isAlignRight = true;
                this.__widget.isAbsoluteBottom = false;
                this.__widget.isAbsoluteTop = false;
                this.__widget.alignMode = Widget.AlignMode.ALWAYS;
                this.__widget.enabled = true;
                break;
            case FitMode.FitHeight:
                this.__widget.top = 0;
                this.__widget.bottom = 0;
                this.__widget.isAlignLeft = false;
                this.__widget.isAlignRight = false;
                this.__widget.isAbsoluteBottom = true;
                this.__widget.isAbsoluteTop = true;
                this.__widget.alignMode = Widget.AlignMode.ALWAYS;
                this.__widget.enabled = true;
                break;
            case FitMode.FitAll:
                this.__widget.left = 0;
                this.__widget.right = 0;
                this.__widget.top = 0;
                this.__widget.bottom = 0;
                this.__widget.isAlignLeft = true;
                this.__widget.isAlignRight = true;
                this.__widget.isAbsoluteBottom = true;
                this.__widget.isAbsoluteTop = true;
                this.__widget.alignMode = Widget.AlignMode.ALWAYS;
                this.__widget.enabled = true;
                break;
            case FitMode.Auto:
                this.__widget.enabled = false;
                if (this.__bkg.spriteFrame) {
                    const { width: bw, height: bh } = this.__bkg.spriteFrame;
                    const { width: sw, height: sh } = view.getVisibleSize();
                    const scale = Math.max(sw / bw, sh / bh);
                    this.__tranform.setContentSize((bw * scale + 0.5) | 0, (bh * scale + 0.5) | 0);
                }
                break;
        }
    }

    /**
     * 通过指定资源路径更换背景图片
     * @param path 图片路径
     * @param bundle 图片所属资源包
     */
    public async changeByPath(path: string, bundle: string = 'resources') {
        const frame = await app.resLoader.loadOne({ path, bundle, type: SpriteFrame });
        frame && this.changeByFrame(frame);
    }

    /**
     * 如果指定图片网址更换背景图片
     * @param url 图片网址
     * @param ext 图片格式
     */
    public async changeByURL(url: string, ext: string = 'jpg') {
        const image = await app.resLoader.loadRemote(url, ImageAsset, ext);
        image && this.changeByFrame(SpriteFrame.createWithImage(image));
    }

    /**
     * 通过指定资源 UUId 更换背景图片
     * @param uuid UUID
     */
    public changeByUUID(uuid: string) {
        const frame = assetManager.assets.get(uuid);
        if (frame instanceof SpriteFrame) {
            this.changeByFrame(frame);
        }
    }

    /**
     * 通过指定精灵帧更换背景图片
     * @param frame 精灵帧
     */
    public changeByFrame(frame: SpriteFrame) {
        if (frame) {
            this.__bkg.spriteFrame = frame;
            this.fitMode = this.editorFitMode;
        }
    }
}
